package com.study.thirdpartyeventconsumer.controller;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/proxy")
public class ForwardProxyController {
    private static final Logger log = LoggerFactory.getLogger(ForwardProxyController.class);

    @RequestMapping(value = "/**", method = {RequestMethod.GET,
            RequestMethod.POST,
            RequestMethod.PUT,
            RequestMethod.DELETE,
            RequestMethod.PATCH})
    public void forwardRequest(
            @RequestHeader HttpHeaders headers,
            @RequestBody(required = false) byte[] body,
            @RequestParam Map<String, String> formParams,
            HttpServletRequest httpRequest, HttpServletResponse result) throws IOException {
        //请求url

        HttpRequest request = new HttpRequest(headers.get("proxyUrl").get(0));
        //请求方式
        request.method(Method.valueOf(httpRequest.getMethod()));
        //请求头
        copyHeaders(headers, request);
        //请求体

        request.body(body);

        if (body != null && body.length > 0) {
            request.body(body);
        } else if (!formParams.isEmpty()) {
            // 将表单参数添加到请求体
            String formData = formParams.entrySet().stream()
                    .map(e -> e.getKey() + "=" + e.getValue())
                    .collect(Collectors.joining("&"));
            request.body(formData);
            request.header("Content-Type", "application/x-www-form-urlencoded");
        }

        log.info("linkedin\r\n url:{} \r\n headers:{}  ", request.getUrl(), request.headers());
        //发送请求
        HttpResponse response = request.execute();
        log.info("linkedin response:{}", response);
        response.headers().forEach((k, v) -> {
            if (k != null) {
                for (String s : v) {
                    if (!k.equals("Content-Encoding") && !k.equals("content-length") && !k.equals("Transfer-Encoding")) {
                        result.addHeader(k, s);
                    }
                }
            }
        });
        byte[] bytes = new byte[response.bodyStream().available()];
        response.bodyStream().read(bytes);
        result.getOutputStream().write(bytes);
        result.setStatus(response.getStatus());
        result.flushBuffer();
    }


    private ResponseEntity<byte[]> wrapResponse(HttpResponse response) {
        HttpHeaders headers = new HttpHeaders();
        response.headers().forEach((k, v) -> {
            if (k != null) headers.addAll(k, v);
        });
        return new ResponseEntity<>(response.bodyBytes(), headers, response.getStatus());
    }

    private void copyHeaders(HttpHeaders headers, HttpRequest httpRequest) {
        headers.entrySet().stream()
                .filter(e -> !isHopByHopHeader(e.getKey()))
                .forEach(e -> httpRequest.header(e.getKey(), e.getValue().get(0)));
    }

    private boolean isHopByHopHeader(String headerName) {
        return headerName.equalsIgnoreCase("Connection") ||
                headerName.equalsIgnoreCase("Keep-Alive") ||
                headerName.equalsIgnoreCase("Proxy-Authenticate") ||
                headerName.equalsIgnoreCase("Proxy-Authorization") ||
                headerName.equalsIgnoreCase("proxyUrl") ||
                headerName.equalsIgnoreCase("TE") ||
                headerName.equalsIgnoreCase("host") ||
                headerName.equalsIgnoreCase("Trailer") ||
                headerName.equalsIgnoreCase("Transfer-Encoding") ||
                headerName.equalsIgnoreCase("Upgrade");
    }

}
